package com.xyht.sca_s.student_manage_system.modules.dormitory.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.auth.entity.Node;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.ApiModelUtil;
import com.xyht.sca_s.student_manage_system.modules.common.entity.SmsImportTask;
import com.xyht.sca_s.student_manage_system.modules.common.entity.SmsImportTaskDetail;
import com.xyht.sca_s.student_manage_system.modules.common.mapper.SmsImportTaskDetailMapper;
import com.xyht.sca_s.student_manage_system.modules.common.mapper.SmsImportTaskMapper;
import com.xyht.sca_s.student_manage_system.modules.dormitory.entity.*;
import com.xyht.sca_s.student_manage_system.modules.dormitory.entity.req.SmsDormitoryAddReq;
import com.xyht.sca_s.student_manage_system.modules.dormitory.entity.req.SmsDormitoryDeletedReq;
import com.xyht.sca_s.student_manage_system.modules.dormitory.entity.req.SmsDormitoryInfoExportReq;
import com.xyht.sca_s.student_manage_system.modules.dormitory.entity.req.SmsDormitoryUpdateReq;
import com.xyht.sca_s.student_manage_system.modules.dormitory.entity.resp.SmsDormitoryExportResp;
import com.xyht.sca_s.student_manage_system.modules.dormitory.entity.resp.SmsDormitoryInfoExportResp;
import com.xyht.sca_s.student_manage_system.modules.dormitory.entity.resp.SmsDormitoryResp;
import com.xyht.sca_s.student_manage_system.modules.dormitory.entity.resp.SmsDormitoryTypeResp;
import com.xyht.sca_s.student_manage_system.modules.dormitory.mapper.*;
import com.xyht.sca_s.student_manage_system.modules.dormitory.service.SmsDormitoryService;
import com.xyht.sca_s.student_manage_system.modules.org.entity.SmsOrgStructure;
import com.xyht.sca_s.student_manage_system.modules.org.mapper.SmsOrgStructureMapper;
import com.xyht.sca_s.student_manage_system.modules.org.util.NodeTreeUtil;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsUser;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsUserMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.SmsWnsChargeCategoryDetail;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.mapper.SmsWnsChargeCategoryDetailMapper;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.TaskDetailReason.*;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.TaskNameExample.TASK_NAME_DORMITORY_OWNERSHIP_IMPORT;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.TaskStatus.TASK_STATUS_DONE;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.TaskStatus.TASK_STATUS_ERR;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.TaskTypeConstant.TASK_TYPE_DORMITORY_OWNERSHIP;
import static com.xyht.sca_s.student_manage_system.modules.dormitory.constant.IsStuConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.dormitory.constant.RuleFlagConstant.FLAG_NORMAL;
import static com.xyht.sca_s.student_manage_system.modules.dormitory.constant.RuleFlagConstant.FLAG_RULE;
import static com.xyht.sca_s.student_manage_system.modules.dormitory.constant.chargeTypeConstant.CHARGE_TYPE_DORMITORY;
import static com.xyht.sca_s.student_manage_system.modules.signUp.constant.SmsSignUpCommonConstant.PER_SHEET_NUM;

/**
 * <p>
 * 宿舍管理表 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2024-01-08
 */
@Service
public class SmsDormitoryServiceImpl extends ServiceImpl<SmsDormitoryMapper, SmsDormitory> implements SmsDormitoryService {


    @Resource
    private SmsDormitoryMapper dormitoryMapper;
    @Resource
    private SmsDormitoryFloorMapper dormitoryFloorMapper;
    @Resource
    private SmsDormitoryBuildingMapper dormitoryBuildingMapper;
    @Resource
    private SmsDormitoryBedMapper dormitoryBedMapper;
    @Resource
    private SmsDormitoryTypeMapper dormitoryTypeMapper;
    @Resource
    private SmsWnsChargeClassificationRelationMapper chargeClassificationRelationMapper;
    @Resource
    private SmsWnsChargeCategoryDetailMapper chargeCategoryDetailMapper;
    @Resource
    private ApiModelUtil apiModelUtil;
    @Resource
    private SmsImportTaskMapper smsImportTaskMapper;
    @Resource
    SmsImportTaskDetailMapper smsImportTaskDetailMapper;
    @Resource
    PlatformTransactionManager transactionManager;
    @Resource
    private SmsOrgStructureMapper smsOrgStructureMapper;
    @Resource
    private NodeTreeUtil nodeTreeUtil;
    @Resource
    private SmsUserMapper smsUserMapper;

    @Override
    @Transactional
    public ResponseResult addDormitory(String userId, SmsDormitoryAddReq addReq) {
        if (isNullOrEmpty(addReq.getFloorId(), addReq.getDormitoryCategory(),addReq.getRuleFlag(),addReq.getDormitoryTypeId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        //校验楼层
        SmsDormitoryFloor smsDormitoryFloor = dormitoryFloorMapper.selectById(addReq.getFloorId());
        if (isNullOrEmpty(smsDormitoryFloor)) {
            return CommonResult.failed(CommonCodeEnum.DORMITORY_FLOOR_NOT_EXIST);
        }
        String buildingId = smsDormitoryFloor.getBuildingId();
        //校验楼栋
        SmsDormitoryBuilding smsDormitoryBuilding = dormitoryBuildingMapper.selectById(buildingId);
        if (isNullOrEmpty(smsDormitoryBuilding)) {
            return CommonResult.failed(CommonCodeEnum.DORMITORY_BUILDING_NOT_EXIST);
        }
        //校验宿舍类型
        SmsDormitoryType dormitoryType = dormitoryTypeMapper.selectById(addReq.getDormitoryTypeId());
        if (isNullOrEmpty(dormitoryType)) {
            return CommonResult.failed(CommonCodeEnum.DORMITORY_TYPE_NOT_EXIST);
        }
        //获取几人间名称
        Integer bedNumber = dormitoryType.getBedNumber();

        Integer ruleFlag = addReq.getRuleFlag();
        //1.普通规则
        if (ruleFlag == FLAG_NORMAL) {
            if (isNullOrEmpty(addReq.getDormitoryNumber())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            //校验名称是否重复
            List<SmsDormitory> houseNumberList = dormitoryMapper.selectList(new LambdaQueryWrapper<SmsDormitory>()
                    .eq(SmsDormitory::getDormitoryNumber, addReq.getDormitoryNumber()));
            if (!houseNumberList.isEmpty()) {
                return CommonResult.failed(CommonCodeEnum.DORMITORY_NAME_EXIST);
            }

            SmsDormitory smsDormitory = new SmsDormitory();
            smsDormitory.setBuildId(smsDormitoryFloor.getBuildingId());
            smsDormitory.setBuildName(smsDormitoryBuilding.getBuildingName());
            smsDormitory.setFloorId(addReq.getFloorId());
            smsDormitory.setFloorName(smsDormitoryFloor.getFloorName());
            smsDormitory.setUserId(userId);
            smsDormitory.setDormitoryNumber(addReq.getDormitoryNumber());
            smsDormitory.setBedNumber(bedNumber);
            smsDormitory.setDormitoryTypeId(addReq.getDormitoryTypeId());
            smsDormitory.setDormitoryCategory(addReq.getDormitoryCategory());
            dormitoryMapper.insert(smsDormitory);

            String dormitoryId = smsDormitory.getId();
            if (isNullOrEmpty(dormitoryId)) {
                return CommonResult.failed(CommonCodeEnum.FAIL);
            }
            //插入床号
            insertDormitoryBed(dormitoryId, bedNumber);
            //2.规则
        } else if (ruleFlag == FLAG_RULE) {
            if (isNullOrEmpty(addReq.getStartHouseNumber(),addReq.getIncreaseNumber(),addReq.getHouseCount())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            //校验门牌数
            Integer houseCount = addReq.getHouseCount();
            if (houseCount < 1) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            List<SmsDormitory> houseNumberList = dormitoryMapper.selectList(new LambdaQueryWrapper<SmsDormitory>()
                    .eq(SmsDormitory::getFloorId, addReq.getFloorId()));
            //2.1.该楼层已设有门牌号
            if (!houseNumberList.isEmpty()) {
                List<Integer> houseNameList = houseNumberList.stream().map(SmsDormitory::getDormitoryNumber).sorted().collect(Collectors.toList());
                //中间楼层被删除 依次填充并添加
                for (int i = 1; i <= houseCount ; i++) {
                    int j = addReq.getStartHouseNumber();
                    while (houseNameList.contains(j)) {
                        j += addReq.getIncreaseNumber();
                    }
                    SmsDormitory smsDormitory = new SmsDormitory();
                    smsDormitory.setFloorId(addReq.getFloorId());
                    smsDormitory.setFloorName(smsDormitoryFloor.getFloorName());
                    smsDormitory.setBuildId(smsDormitoryFloor.getBuildingId());
                    smsDormitory.setBuildName(smsDormitoryBuilding.getBuildingName());
                    smsDormitory.setUserId(userId);
                    smsDormitory.setDormitoryNumber(j);
                    smsDormitory.setBedNumber(bedNumber);
                    smsDormitory.setDormitoryTypeId(addReq.getDormitoryTypeId());
                    smsDormitory.setDormitoryCategory(addReq.getDormitoryCategory());
                    dormitoryMapper.insert(smsDormitory);

                    String dormitoryId = smsDormitory.getId();
                    if (isNullOrEmpty(dormitoryId)) {
                        return CommonResult.failed(CommonCodeEnum.FAIL);
                    }
                    //插入床号
                    insertDormitoryBed(dormitoryId, bedNumber);

                    houseNameList.add(j);
                }

                //2.2 未有门牌号
            }else {
                for (int i = 0; i < houseCount; i++) {
                    SmsDormitory smsDormitory = new SmsDormitory();
                    smsDormitory.setBuildId(smsDormitoryFloor.getBuildingId());
                    smsDormitory.setBuildName(smsDormitoryBuilding.getBuildingName());
                    smsDormitory.setFloorId(addReq.getFloorId());
                    smsDormitory.setFloorName(smsDormitoryFloor.getFloorName());
                    smsDormitory.setUserId(userId);
                    smsDormitory.setBedNumber(bedNumber);
                    smsDormitory.setDormitoryTypeId(addReq.getDormitoryTypeId());
                    smsDormitory.setDormitoryNumber(addReq.getStartHouseNumber() + addReq.getIncreaseNumber() * i);
                    smsDormitory.setDormitoryCategory(addReq.getDormitoryCategory());
                    dormitoryMapper.insert(smsDormitory);

                    String dormitoryId = smsDormitory.getId();
                    if (isNullOrEmpty(dormitoryId)) {
                        return CommonResult.failed(CommonCodeEnum.FAIL);
                    }
                    //插入床号
                    insertDormitoryBed(dormitoryId, bedNumber);
                }
            }

        }else {
            return CommonResult.failed(CommonCodeEnum.FAIL);
        }

        return CommonResult.success();
    }


    @Override
    @Transactional
    public ResponseResult deletedDormitory(SmsDormitoryDeletedReq deletedReq) {
        if (deletedReq.getIdList() == null || deletedReq.getIdList().size() < 1) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        List<SmsDormitory> houseNumberList = dormitoryMapper.selectBatchIds(deletedReq.getIdList());
        if (houseNumberList.isEmpty()) {
            return CommonResult.failed(CommonCodeEnum.DORMITORY_NOT_EXIST);
        }
        //删除宿舍
        dormitoryMapper.deleteBatchIds(deletedReq.getIdList());
        //删除床绑带的学生
        dormitoryBedMapper.delete(new LambdaQueryWrapper<SmsDormitoryBed>().in(SmsDormitoryBed::getDormitoryId,deletedReq.getIdList()));
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult updateDormitory(SmsDormitoryUpdateReq updateReq, String userId) {
        if (isNullOrEmpty(updateReq.getId(),updateReq.getDormitoryNumber(),updateReq.getDormitoryCategory(),updateReq.getDormitoryTypeId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsDormitory smsDormitory = dormitoryMapper.selectById(updateReq.getId());
        if (isNullOrEmpty(smsDormitory)) {
            return CommonResult.failed(CommonCodeEnum.DORMITORY_NOT_EXIST);
        }
        //校验宿舍类型
        SmsDormitoryType smsDormitoryType = dormitoryTypeMapper.selectById(updateReq.getDormitoryTypeId());
        if (isNullOrEmpty(smsDormitoryType)) {
            return CommonResult.failed(CommonCodeEnum.DORMITORY_TYPE_NOT_EXIST);
        }
        //获取几人间名称
        Integer bedNumber = smsDormitoryType.getBedNumber();

        //校验宿舍名是否重复
        List<SmsDormitory> houseNumberList = dormitoryMapper.selectList(new LambdaQueryWrapper<SmsDormitory>()
                .eq(SmsDormitory::getDormitoryNumber, updateReq.getDormitoryNumber())
                .ne(SmsDormitory::getId, updateReq.getId()));
        if (!houseNumberList.isEmpty()) {
            return CommonResult.failed(CommonCodeEnum.DORMITORY_NAME_EXIST);
        }

        //房间里已被占用的床数
        List<SmsDormitoryBed> dormitoryBedStuList = dormitoryBedMapper.selectList(new LambdaQueryWrapper<SmsDormitoryBed>()
                .eq(SmsDormitoryBed::getDormitoryId, updateReq.getId()).isNotNull(SmsDormitoryBed::getStuUserId)
                .eq(SmsDormitoryBed::getIsStu,IS_STUDENT)
                .orderByDesc(SmsDormitoryBed::getBedNo));
        //最后一个被学生占用的床号
        int stuCount = 0;
        if (!dormitoryBedStuList.isEmpty()) {
            stuCount = dormitoryBedStuList.get(0).getBedNo();
        }
        //校验修改的床数不能小于最后一个学生占用的床号
        if (bedNumber < stuCount) {
            return CommonResult.failed(CommonCodeEnum.DORMITORY_UPDATE_BED_OVER);
        }
        //1.修改宿舍
        BeanUtils.copyProperties(updateReq,smsDormitory);
        dormitoryMapper.updateById(smsDormitory);

        //2.修改床位表
        //计算宿舍下总的床位
        List<SmsDormitoryBed> dormitoryBedList = dormitoryBedMapper.selectList(new LambdaQueryWrapper<SmsDormitoryBed>()
                .eq(SmsDormitoryBed::getDormitoryId, updateReq.getId()));
        //2.1已有的床位
        if (!dormitoryBedList.isEmpty()) {
            List<Integer> bedNoList = dormitoryBedList.stream().map(SmsDormitoryBed::getBedNo).collect(Collectors.toList());
            //2.1.1没有学生站位先删除后添加
            if (dormitoryBedStuList.isEmpty()) {
                dormitoryBedMapper.delete(new LambdaQueryWrapper<SmsDormitoryBed>()
                        .eq(SmsDormitoryBed::getDormitoryId, updateReq.getId()));
                insertDormitoryBed(smsDormitory.getId(), bedNumber);
            }else {
                //2.1.2有学生站位的往后添加
                //最后一个被学生占用的床号
                Integer lastStuBedNo = dormitoryBedStuList.get(0).getBedNo();
                if (!bedNumber.equals(bedNoList.size())) {
                    int addBedNo = bedNumber - lastStuBedNo;
                    for (int i = 1; i <= addBedNo; i++) {
                        SmsDormitoryBed smsDormitoryBed = new SmsDormitoryBed();
                        smsDormitoryBed.setDormitoryId(smsDormitory.getId());
                        smsDormitoryBed.setBedNo(i + lastStuBedNo);
                        dormitoryBedMapper.insert(smsDormitoryBed);
                    }
                }
            }
        //2.2 没有床位依次添加
        }else {
            insertDormitoryBed(smsDormitory.getId(), bedNumber);
        }


        return CommonResult.success();
    }

    @Override
    public ResponseResult getDormitoryList(String buildId, String floorId, String dormitoryId, Integer sex, Integer bedNumber, String feeStandards, Integer pageNum, Integer pageSize, String name, String buildingDescription) {
        Page<SmsDormitory> page = new Page<>(pageNum,pageSize);
        LambdaQueryWrapper<SmsDormitory> lambdaQueryWrapper = new LambdaQueryWrapper<SmsDormitory>()
                .orderByAsc(SmsDormitory::getBuildName)
                .orderByAsc(SmsDormitory::getFloorName)
                .orderByAsc(SmsDormitory::getDormitoryNumber);

        if (!isNullOrEmpty(name)) {
            lambdaQueryWrapper.eq(SmsDormitory::getDormitoryNumber,name);
        }
        if (!isNullOrEmpty(buildId)) {
            lambdaQueryWrapper.eq(SmsDormitory::getBuildId,buildId);
        }
        if (!isNullOrEmpty(buildingDescription)) {
            List<String> filterIdList = dormitoryBuildingMapper.selectList(new LambdaQueryWrapper<SmsDormitoryBuilding>()
                    .like(SmsDormitoryBuilding::getBuildingDescription, buildingDescription))
                    .stream()
                    .map(SmsDormitoryBuilding::getId).collect(Collectors.toList());
            if (filterIdList.isEmpty()) {
                lambdaQueryWrapper.in(SmsDormitory::getBuildId, "");
            } else {
                lambdaQueryWrapper.in(SmsDormitory::getBuildId, filterIdList);
            }

        }
        if (!isNullOrEmpty(floorId)) {
            lambdaQueryWrapper.eq(SmsDormitory::getFloorId,floorId);
        }
        if (!isNullOrEmpty(dormitoryId)) {
            lambdaQueryWrapper.eq(SmsDormitory::getId,dormitoryId);
        }
        if (!isNullOrEmpty(sex)) {
            lambdaQueryWrapper.eq(SmsDormitory::getDormitoryCategory,sex);
        }
        if (!isNullOrEmpty(bedNumber)) {
            lambdaQueryWrapper.eq(SmsDormitory::getBedNumber,bedNumber);
        }
        dormitoryMapper.selectPage(page, lambdaQueryWrapper);
        List<SmsDormitoryResp> houseNumberList = page.getRecords()
                .stream()
                .map(smsDormitory -> {
                    //宿舍信息
                    SmsDormitoryResp smsDormitoryResp = new SmsDormitoryResp();
                    SmsDormitoryTypeResp dormitoryTypeResp = new SmsDormitoryTypeResp();
                    BeanUtils.copyProperties(smsDormitory, smsDormitoryResp);
                    //宿舍类型
                    SmsDormitoryType smsDormitoryType = dormitoryTypeMapper.selectById(smsDormitory.getDormitoryTypeId());
                    if (!isNullOrEmpty(smsDormitoryType)) {
                        BeanUtils.copyProperties(smsDormitoryType,dormitoryTypeResp);
                        //收费标准
                        List<SmsWnsChargeClassificationRelation> relationList = chargeClassificationRelationMapper.selectList(new LambdaQueryWrapper<SmsWnsChargeClassificationRelation>()
                                .eq(SmsWnsChargeClassificationRelation::getId, smsDormitoryType.getId())
                                .eq(SmsWnsChargeClassificationRelation::getType, CHARGE_TYPE_DORMITORY));
                        if (!relationList.isEmpty()) {
                            String chargeDetailId = relationList.get(0).getChargeDetailId();
                            SmsWnsChargeCategoryDetail smsWnsChargeCategoryDetail = chargeCategoryDetailMapper.selectById(chargeDetailId);
                            if (!isNullOrEmpty(smsWnsChargeCategoryDetail)) {
                                smsDormitoryResp.setCharge(smsWnsChargeCategoryDetail.getDefaultPrice());
                            }

                        }

                    }
                    smsDormitoryResp.setDormitoryTypeResp(dormitoryTypeResp);

                    //楼层信息
                    SmsDormitoryFloor dormitoryFloor = dormitoryFloorMapper.selectById(smsDormitory.getFloorId());
                    if (!isNullOrEmpty(dormitoryFloor)) {
                        smsDormitoryResp.setFloorName(dormitoryFloor.getFloorName());
                        //楼栋信息
                        SmsDormitoryBuilding smsDormitoryBuilding = dormitoryBuildingMapper.selectById(dormitoryFloor.getBuildingId());
                        if (!isNullOrEmpty(smsDormitoryBuilding)) {
                            smsDormitoryResp.setBuildingName(smsDormitoryBuilding.getBuildingName());
                            smsDormitoryResp.setBuildingDescription(smsDormitoryBuilding.getBuildingDescription());
                        }
                    }
                    //是否有学生占用标识 [0: 没有 1:有学生占有]
                    Integer isStuCount = dormitoryBedMapper.selectCount(new LambdaQueryWrapper<SmsDormitoryBed>()
                            .eq(SmsDormitoryBed::getDormitoryId, smsDormitory.getId())
                            .eq(SmsDormitoryBed::getIsStu, IS_STUDENT));
                    if (isStuCount > 0) {
                        smsDormitoryResp.setIsStu(IS_STUDENT);
                    }else {
                        smsDormitoryResp.setIsStu(NOT_STUDENT);
                    }
                    //是否分配组织[0:没有 1:有]
                    Integer isBelongCount = dormitoryBedMapper.selectCount(new LambdaQueryWrapper<SmsDormitoryBed>()
                            .eq(SmsDormitoryBed::getDormitoryId, smsDormitory.getId())
                            .eq(SmsDormitoryBed::getIsOrg, IS_ORG));
                    if (isBelongCount > 0) {
                        smsDormitoryResp.setIsOrg(IS_ORG);
                    }else {
                        smsDormitoryResp.setIsOrg(NOT_ORG);
                    }
                    return smsDormitoryResp;
                })
                .collect(Collectors.toList());
        int total = (int) page.getTotal();
        return CommonResult.success(houseNumberList,total);
    }

    @Override
    @Async
    public Future<ResponseResult> exportBuildInfo(SmsDormitoryInfoExportReq req, HttpServletResponse response) {

        try{
            LambdaQueryWrapper<SmsDormitory> lambdaQueryWrapper = new LambdaQueryWrapper<SmsDormitory>()
                    .orderByAsc(SmsDormitory::getBuildName)
                    .orderByAsc(SmsDormitory::getFloorName)
                    .orderByAsc(SmsDormitory::getDormitoryNumber);

            if (!isNullOrEmpty(req.getName())) {
                lambdaQueryWrapper.eq(SmsDormitory::getDormitoryNumber,req.getName());
            }
            if (!isNullOrEmpty(req.getBuildId())) {
                lambdaQueryWrapper.eq(SmsDormitory::getBuildId,req.getBuildId());
            }
            if (!isNullOrEmpty(req.getFloorId())) {
                lambdaQueryWrapper.eq(SmsDormitory::getFloorId,req.getFloorId());
            }
            if (!isNullOrEmpty(req.getDormitoryId())) {
                lambdaQueryWrapper.eq(SmsDormitory::getId,req.getDormitoryId());
            }
            if (!isNullOrEmpty(req.getSex())) {
                lambdaQueryWrapper.eq(SmsDormitory::getDormitoryCategory,req.getSex());
            }
            if (!isNullOrEmpty(req.getBedNumber())) {
                lambdaQueryWrapper.eq(SmsDormitory::getBedNumber,req.getBedNumber());
            }
            List<SmsDormitoryExportResp> list = new ArrayList<>();
            List<SmsDormitory> dormitoryList = dormitoryMapper.selectList(lambdaQueryWrapper);
            if (!dormitoryList.isEmpty()) {
                for (SmsDormitory smsDormitory : dormitoryList) {
                    String dormitoryTypeId = smsDormitory.getDormitoryTypeId();
                    SmsDormitoryType smsDormitoryType = dormitoryTypeMapper.selectById(dormitoryTypeId);
                    List<SmsDormitoryBed> dormitoryBedList = dormitoryBedMapper.selectList(new LambdaQueryWrapper<SmsDormitoryBed>()
                            .eq(SmsDormitoryBed::getDormitoryId, smsDormitory.getId()));
                    if (!dormitoryBedList.isEmpty()) {
                        for (SmsDormitoryBed smsDormitoryBed : dormitoryBedList) {
                            SmsDormitoryExportResp smsDormitoryExportResp = new SmsDormitoryExportResp();
                            Integer buildName = smsDormitory.getBuildName();
                            Integer floorName = smsDormitory.getFloorName();
                            Integer dormitoryNumber = smsDormitory.getDormitoryNumber();
                            Integer dormitoryCategory = smsDormitory.getDormitoryCategory();
                            Integer bedNumber = smsDormitory.getBedNumber();
                            if (!isNullOrEmpty(smsDormitoryType)) {
                                smsDormitoryExportResp.setDormitoryType(smsDormitoryType.getTypeName());
                            }
                            smsDormitoryExportResp.setBuildingName(buildName);
                            smsDormitoryExportResp.setFloorName(floorName);
                            smsDormitoryExportResp.setDormitoryCategory(dormitoryCategory);
                            smsDormitoryExportResp.setDormitoryNumber(dormitoryNumber);
                            smsDormitoryExportResp.setBedNumber(bedNumber);
                            smsDormitoryExportResp.setBedsNo(smsDormitoryBed.getBedNo());
                            list.add(smsDormitoryExportResp);
                        }

                    }
                }
            }

        //表头数据
        String[] header = req.getLimitColumn().toArray(new String[0]);
        double sheetNum;
        //声明一个工作簿
        HSSFWorkbook workbook = new HSSFWorkbook();
        if (list.size() > 0) {
            sheetNum = Math.ceil((double) list.size() / PER_SHEET_NUM);
            for (int k = 0; k < sheetNum; k++) {
                //生成一个表格，设置表格名称为"资源导出表"
                HSSFSheet sheet = workbook.createSheet("宿舍信息模版导出表" + (k + 1));

                //设置表格列宽度为10个字节
                sheet.setDefaultColumnWidth(12);
                //创建标题的显示样式
                HSSFCellStyle headerStyle = workbook.createCellStyle();
                headerStyle.setFillForegroundColor(IndexedColors.YELLOW.index);
                headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

                HSSFFont f = workbook.createFont();
                f.setFontHeightInPoints((short) 10);//字号
                f.setBold(true);//加粗
                headerStyle.setFont(f);
                //创建第一行表头
                HSSFRow headrow = sheet.createRow(0);

                //遍历添加表头(下面模拟遍历学生，也是同样的操作过程)
                for (int i = 0; i < header.length + 1; i++) {
                    //创建一个单元格
                    HSSFCell cell = headrow.createCell(i);

                    if (i == 0) {
                        //创建一个内容对象
                        HSSFRichTextString text = new HSSFRichTextString("序号");
                        //将内容对象的文字内容写入到单元格中
                        cell.setCellValue(text);
                        cell.setCellStyle(headerStyle);
                        continue;
                    }
                    //创建一个内容对象
                    String header1 = apiModelUtil.getFieldValueByFieldName(SmsDormitoryExportResp.class, header[i - 1]);
                    HSSFRichTextString text = new HSSFRichTextString(header1);

                    //将内容对象的文字内容写入到单元格中
                    cell.setCellValue(text);
                    cell.setCellStyle(headerStyle);
                }


                int range = PER_SHEET_NUM;
                if (k + 1 == sheetNum) {
                    range = list.size() - (PER_SHEET_NUM) * k;
                }
                for (int i = 0; i < range; i++) {
                    //创建一行
                    HSSFRow row1 = sheet.createRow(i + 1);
                    SmsDormitoryExportResp dormitoryExportResp = list.get((PER_SHEET_NUM) * k + i);
                    Map map = JSONObject.parseObject(JSON.toJSONString(dormitoryExportResp), Map.class);
                    row1.createCell(0).setCellValue(new HSSFRichTextString(i + 1 + ""));
                    for (int j = 0; j < header.length; j++) {
                        String rowContent = "";
                        if(!isNullOrEmpty(map.get(header[j]))) {

                            if (header[j].equals("buildingName")) {
                                rowContent = map.get(header[j]) + "栋";
                            } else if (header[j].equals("floorName")) {
                                rowContent = map.get(header[j]) + "楼";
                            } else if (header[j].equals("dormitoryNumber")) {
                                rowContent = map.get(header[j]) + "号";
                            } else if (header[j].equals("dormitoryCategory")) {
                                Integer dormitoryCategory = dormitoryExportResp.getDormitoryCategory();
                                if (dormitoryCategory == 1) {
                                    rowContent = "女寝室";
                                } else if (dormitoryCategory == 2) {
                                    rowContent = "男寝室";
                                }
                            } else if (header[j].equals("bedNumber")) {
                                rowContent = map.get(header[j]) + "张";
                            } else if (header[j].equals("bedsNo")) {
                                rowContent = map.get(header[j]) + "号床";
                            } else {
                                rowContent = String.valueOf(map.get(header[j]));
                            }
                        }
                        row1.createCell(j + 1).setCellValue(new HSSFRichTextString(rowContent));
                    }

                }
            }
        }

        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("宿舍信息模版导出表.xlsx", "utf-8"));
        response.setCharacterEncoding("utf-8");
        response.setHeader("file-type", "download");
        response.setHeader("file-name", URLEncoder.encode("宿舍信息模版导出表.xlsx", "utf-8"));
        response.setHeader("Access-Control-Expose-Headers", "file-type,file-name");
        //刷新缓冲
        response.flushBuffer();
        //workbook将Excel写入到response的输出流中，供页面下载
        OutputStream os = response.getOutputStream();
        workbook.write(os);

        workbook.close();
        os.close();
    } catch (Exception e) {
        e.printStackTrace();
        return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
    }
        return null;
    }

    @Override
    @Async
    public Future<ResponseResult> batchDormitoryOwnership(Map<String, Object> map, String user_id) {
        JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(map));
        List<SmsDormitoryInfoExportResp> dormitoryExportBatchReqs = JSONObject.parseArray(JSON.toJSONString(jsonObject.get("list")), SmsDormitoryInfoExportResp.class);
        if (dormitoryExportBatchReqs == null || dormitoryExportBatchReqs.size() < 1) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
        }

        //创建导入任务
        SmsImportTask smsImportTask = new SmsImportTask();
        smsImportTask.setTaskName(TASK_NAME_DORMITORY_OWNERSHIP_IMPORT);
        smsImportTask.setUserId(user_id);
        smsImportTask.setTaskType(TASK_TYPE_DORMITORY_OWNERSHIP);
        smsImportTaskMapper.insert(smsImportTask);
        batchAddDormitoryOwnership(dormitoryExportBatchReqs, smsImportTask.getId(),user_id);
        return new AsyncResult<>(CommonResult.success());
    }

    private void batchAddDormitoryOwnership( List<SmsDormitoryInfoExportResp> dormitoryExportBatchReqs, String id,String userId) {

        int OFFSET_ROW = 1;
        int task_status = TASK_STATUS_DONE;
        for (int i = 0; i < dormitoryExportBatchReqs.size(); i++) {
            //开启事务
            DefaultTransactionDefinition dt = new DefaultTransactionDefinition();
            // 嵌套事务 PROPAGATION_REQUIRES_NEW 每次开启一个新的事务
            dt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
            // 设置嵌套事务
            TransactionStatus status = transactionManager.getTransaction(dt);
            try {
                SmsDormitoryInfoExportResp storage = dormitoryExportBatchReqs.get(i);
                if (isNullOrEmpty(storage.getStuCollege(),storage.getStuClass(),
                        storage.getStuGrade(),storage.getStuMajor())) {
                    continue;
                }


                if (isNullOrEmpty(storage.getBuildingName(),storage.getFloorName(),storage.getDormitoryNumber(),
                        storage.getBedsNo(),storage.getStuCollege(),storage.getStuClass(),
                        storage.getStuGrade(),storage.getStuMajor())) {
                    transactionManager.rollback(status);
                    task_status = TASK_STATUS_ERR;
                    createTeacherImportTaskDetail(id, REASON_INVALID_PARAM, (i + OFFSET_ROW) + "");
                    continue;
                }


                //校验宿舍是否存在
                List<SmsDormitory> dormitoryList = dormitoryMapper.selectList(new LambdaQueryWrapper<SmsDormitory>()
                        .like(SmsDormitory::getBuildName, storage.getBuildingName())
                        .like(SmsDormitory::getFloorName, storage.getFloorName())
                        .like(SmsDormitory::getDormitoryNumber, storage.getDormitoryNumber()));
                if (dormitoryList.isEmpty()) {
                    transactionManager.rollback(status);
                    task_status = TASK_STATUS_ERR;
                    createTeacherImportTaskDetail(id, REASON_DORMITORY_NOT_EXIST, (i + OFFSET_ROW) + "");
                    continue;
                }
                //校验宿舍床位是否存在
                SmsDormitory smsDormitory = dormitoryList.get(0);
                String dormitoryId = smsDormitory.getId();
                List<SmsDormitoryBed> dormitoryBedList = dormitoryBedMapper.selectList(new LambdaQueryWrapper<SmsDormitoryBed>()
                        .eq(SmsDormitoryBed::getDormitoryId, dormitoryId)
                        .like(SmsDormitoryBed::getBedNo, storage.getBedsNo()));
                if (dormitoryBedList.isEmpty()) {
                    transactionManager.rollback(status);
                    task_status = TASK_STATUS_ERR;
                    createTeacherImportTaskDetail(id, REASON_DORMITORY_BED_NO_NOT_EXIST, (i + OFFSET_ROW) + "");
                    continue;
                }
                SmsDormitoryBed smsDormitoryBed = dormitoryBedList.get(0);

                //校验该床位是否已分配组织 学生
                Integer isOrg = smsDormitoryBed.getIsOrg();
                Integer isStu = smsDormitoryBed.getIsStu();
                if (isOrg == IS_STUDENT || isStu == IS_STUDENT || !isNullOrEmpty(smsDormitoryBed.getStuCollege())) {
                    transactionManager.rollback(status);
                    task_status = TASK_STATUS_ERR;
                    createTeacherImportTaskDetail(id, REASON_DORMITORY_BED_ORG_EXIST, (i + OFFSET_ROW) + "");
                    continue;
                }
                //校验院系专业年级班级是否存在
                String stuCollege = storage.getStuCollege();
                String stuMajor = storage.getStuMajor();
                String stuGrade = storage.getStuGrade();
                String stuClass = storage.getStuClass();
                QueryWrapper<SmsOrgStructure> orgWrapper = new QueryWrapper<>();
                List<SmsOrgStructure> orgList = smsOrgStructureMapper.selectList(orgWrapper);
                orgWrapper.lambda().eq(SmsOrgStructure::getOrgName, stuCollege);
                SmsOrgStructure collegeOrg = smsOrgStructureMapper.selectOne(orgWrapper);
                if (collegeOrg == null) {
                    transactionManager.rollback(status);
                    createTeacherImportTaskDetail(id, REASON_ORG_COLLEGE_NOT_EXIST, (i + OFFSET_ROW) + "");
                    task_status = TASK_STATUS_ERR;
                    continue;
                }
                List<Node> nodeList = new ArrayList<>();
                for (SmsOrgStructure structure : orgList) {
                    Node node = new Node();
                    BeanUtils.copyProperties(structure, node);
                    nodeList.add(node);
                }
                Node collegeNode = nodeTreeUtil.getChildNodesTree(nodeList, collegeOrg.getId());
                List<Node> childNode = collegeNode.getChildNodeList();
                List<Node> majorNode = childNode.stream()
                        .filter(node -> node.getOrgName().equals(stuMajor))
                        .collect(Collectors.toList());
                if (majorNode.size() < 1) {
                    transactionManager.rollback(status);
                    createTeacherImportTaskDetail(id, REASON_ORG_MAJOR_NOT_EXIST, (i + OFFSET_ROW) + "");
                    task_status = TASK_STATUS_ERR;
                    continue;
                }
                List<Node> gradeNode = majorNode.get(0).getChildNodeList().stream()
                        .filter(node -> node.getOrgName().equals(stuGrade))
                        .collect(Collectors.toList());
                if (gradeNode.size() < 1) {
                    transactionManager.rollback(status);
                    createTeacherImportTaskDetail(id, REASON_ORG_GRADE_NOT_EXIST, (i + OFFSET_ROW) + "");
                    task_status = TASK_STATUS_ERR;
                    continue;
                }
                List<Node> classNode = gradeNode.get(0).getChildNodeList().stream()
                        .filter(node -> node.getOrgName().equals(stuClass))
                        .collect(Collectors.toList());
                if (classNode.size() < 1) {
                    transactionManager.rollback(status);
                    createTeacherImportTaskDetail(id, REASON_ORG_CLASS_NOT_EXIST, (i + OFFSET_ROW) + "");
                    task_status = TASK_STATUS_ERR;
                    continue;
                }
                //检验学生
                if (!isNullOrEmpty(storage.getStuIdCard())) {
                    List<SmsUser> userList = smsUserMapper.selectList(new LambdaQueryWrapper<SmsUser>()
                            .eq(SmsUser::getTel, storage.getStuTel()));
                    if (userList.isEmpty()) {
                        transactionManager.rollback(status);
                        task_status = TASK_STATUS_ERR;
                        createTeacherImportTaskDetail(id, REASON_DORMITORY_USER_NOT_EXIST, (i + OFFSET_ROW) + "");
                        continue;
                    }else {
                        String stuUserId = userList.get(0).getId();
                        //检验学生是否已有床位
                        List<SmsDormitoryBed> dormitoryStuBedList = dormitoryBedMapper.selectList(new LambdaQueryWrapper<SmsDormitoryBed>()
                                .eq(SmsDormitoryBed::getStuUserId, stuUserId));
                        if (!dormitoryStuBedList.isEmpty()) {
                            transactionManager.rollback(status);
                            task_status = TASK_STATUS_ERR;
                            createTeacherImportTaskDetail(id, REASON_DORMITORY_USER_EXIST, (i + OFFSET_ROW) + "");
                            continue;
                        }
                        smsDormitoryBed.setStuUserId(stuUserId);
                        smsDormitoryBed.setIsStu(IS_STUDENT);
                    }
                } else {
                    smsDormitoryBed.setIsStu(NOT_STUDENT);
                }

                smsDormitoryBed.setStuCollege(String.valueOf(collegeOrg.getId()));
                smsDormitoryBed.setStuGrade(String.valueOf(gradeNode.get(0).getId()));
                smsDormitoryBed.setStuMajor(String.valueOf(majorNode.get(0).getId()));
                smsDormitoryBed.setStuClass(String.valueOf(classNode.get(0).getId()));
                smsDormitoryBed.setIsOrg(IS_ORG);


                dormitoryBedMapper.updateById(smsDormitoryBed);
                transactionManager.commit(status);
            } catch (Exception e) {
                transactionManager.rollback(status);
                task_status = TASK_STATUS_ERR;
                createTeacherImportTaskDetail(id, REASON_IMPORT_ERR, (i + OFFSET_ROW) + "");
            } finally {
                if (status.isNewTransaction() && !status.isCompleted()) {
                    transactionManager.commit(status);
                }
            }
        }

        SmsImportTask smsImportTask = new SmsImportTask();
        smsImportTask.setId(id);
        smsImportTask.setStatus(task_status);
        smsImportTaskMapper.updateById(smsImportTask);
    }

    private void createTeacherImportTaskDetail(String id, String reason, String row) {
        SmsImportTaskDetail smsImportTaskDetail = new SmsImportTaskDetail();
        smsImportTaskDetail.setTaskId(id);
        smsImportTaskDetail.setFailReason(reason);
        smsImportTaskDetail.setFailRow(row);
        smsImportTaskDetailMapper.insert(smsImportTaskDetail);
    }


    /**
     * 插入床号
     * @param dormitoryId 宿舍id
     * @param bedNumber 床位数
     */
    private void insertDormitoryBed(String dormitoryId, Integer bedNumber){
        //添加宿舍
        for (int i = 1; i <= bedNumber; i++) {
            SmsDormitoryBed smsDormitoryBed = new SmsDormitoryBed();
            smsDormitoryBed.setDormitoryId(dormitoryId);
            smsDormitoryBed.setBedNo(i);
            smsDormitoryBed.setIsOrg(NOT_ORG);
            smsDormitoryBed.setIsStu(NOT_STUDENT);
            dormitoryBedMapper.insert(smsDormitoryBed);
        }
    }
}
